package com.wolf.etl.core.transform;

import com.wolf.etl.core.ETLManager;
import com.wolf.etl.core.WriteBackManager;
import com.wolf.etl.model.*;
import com.wolf.etl.vo.ColumnDesc;
import com.wolf.exception.WolfException;
import com.wolf.util.RandomUtils;
import com.wolf.vo.BaseResult;
import com.wolf.vo.KeyValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by tommy's father on 2017/8/26.
 */
public abstract class AbstractTransform {

    private static Logger logger = LoggerFactory.getLogger(AbstractTransform.class);

    private static final String logger_prefix = "wolf-etl#com.wolf.etl.core.transform#AbstractTransform";

    private static final Object lock = new Object();
    protected ETLManager manager;
    protected EtlDefineModel etlDefineModel;
    protected EtlTableModel etlTableModel;
    protected List<KeyValuePair> sqls = new ArrayList<KeyValuePair>();
    protected Long tabId = 0L;
    protected Long pTabId = 0L;
    protected List<EtlTransformDefineModel> transformDefineModels;
    protected String sql = null;
    protected Long srcDataSourceId = null;
    protected Long targetDataSourceId = null;
    protected List<Map<String, ColumnDesc>> srcData;
    protected List<EtlTableOrderbyModel> orderbys;
    protected List<EtlTableFilterModel> filters;


    public static final String TRANSFORM_CLASSNAME_FORMAT = "%s.%sTransform";

    protected String HEAD_ITEM_KEY = "000000";

    private WriteBackManager writeBackManager;

    protected void genRandomKey() {
        HEAD_ITEM_KEY = String.valueOf(new Date().getTime()).concat(RandomUtils.getRandomKey(6));
    }

    public String getCountSql(){
        return "";
    }

    public static AbstractTransform getInstance(ETLManager manager) {
//        synchronized (lock) {
            try {
                String packageName = getPackageName();
                String className = "Map";

                logger.info("开始转换");
//                if (manager.getSrcDataSourceId() == manager.getTargetDataSourceId()) {
//                    className = "Sql";
//                } else {
//                    className = "Map";
//                }

                Class<?> clazz = Class.forName(String.format(TRANSFORM_CLASSNAME_FORMAT, packageName, className));
                AbstractTransform abstractTransform = (AbstractTransform) manager.getBeanManager().createBean(clazz);

                abstractTransform.manager = manager;
                abstractTransform.etlDefineModel = manager.getEtlDefineModel();
                abstractTransform.tabId = manager.getTabId();
                abstractTransform.pTabId = manager.getParentTabId();
                abstractTransform.etlTableModel = manager.getTableModel();
                abstractTransform.srcDataSourceId = manager.getSrcDataSourceId();
                abstractTransform.targetDataSourceId = manager.getTargetDataSourceId();
                abstractTransform.orderbys = manager.findOrderby(manager.getTabId());
                abstractTransform.filters = manager.findEtlTableFilterModels(manager.getTabId());
                manager.buildDatabaseManager();

                return abstractTransform;
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
//        }
        String message = "Can't[source datasource id=>%s,target datasource id=>%s] find any concrete implement class.";

        throw new WolfException(String.format(message, manager.getSrcDataSourceId(),
                manager.getTargetDataSourceId()));
    }

    public abstract BaseResult doTransform();

    private String findSqlByTabId(Long tabId) {
        for (KeyValuePair kvp : sqls) {
            if (tabId == Long.parseLong(kvp.getKey())) {
                return kvp.getValue();
            }
        }
        throw new WolfException(String.format("Can't find any sql info by the table id[%s]", tabId));
    }

    protected void appendSourceSql(String sql) {
        manager.appendSourceSql(sql);
    }

    protected void appendTargetSql(String sql) {
        manager.appendTargetSql(sql);
    }

    protected BaseResult doSrcExecute() {
        return manager.doSrcExecute();
    }

    int needCommit = 0;

    protected void needCommit() {
        if (needCommit > 0) {
            return;
        }
        manager.needCommit();
    }

    protected void setReferenceKey(KeyValuePair keyValuePair) {
        manager.setReferenceKey(keyValuePair);
    }

    protected void setResults(int[] results) {
        manager.setResults(results);
    }


    public BaseResult beforeTransform(List<EtlTransformDefineModel> vos) {

        this.transformDefineModels = vos;

        return BaseResult.getSuccess();
    }

    /**
     * 检查规则
     *
     * @return
     */
    private BaseResult checkRule() {
//        List<EtlTransformRuleModel> ruleModels = manager.findEtlTransformRuleModelsById(transformDefineModel.getId());
//
//        //pretreatment
//        BaseResult result = manager.testCheck(ruleModels,
//                transformDefineModel.getSrc_column_name(),
//                transformDefineModel.getTarget_column_name());
//
//        if (!result.getSuccess()) {
//            return result;
//        }
//
//        //convert
//        this.manager.convert(transformDefineModel, ruleModels, etlTableModel.getAlias());

        return BaseResult.getSuccess();
    }

//    public BaseResult beforeTransform(EtlTransformDefineModel transformDefineModel) {
//        this.transformDefineModel = transformDefineModel;
//        sql = manager.buildSql(etlTableModel);
//
//        List<EtlTransformRuleModel> ruleModels = manager.findEtlTransformRuleModelsById(transformDefineModel.getId());
//
//        //pretreatment
//        BaseResult result = manager.testCheck(ruleModels,
//                transformDefineModel.getSrc_column_name(),
//                transformDefineModel.getTarget_column_name());
//
//        if (!result.getSuccess()) {
//            return result;
//        }
//
//        //convert
//        this.manager.convert(transformDefineModel, ruleModels, etlTableModel.getAlias());
//
//        return result;
//    }

    public BaseResult executeTransform() {

        //
        checkRule();

        //insert
        BaseResult result = doTransform();
        if (!result.isSucc()) {
            logger.info(result.getMessage());
            return result;
        }
        //write back
        //result = writeBackManager.writeBack(tabId);
        return result;
    }

    /**
     * @return
     */
    private WriteBackManager getWriteBackManager() {
        WriteBackManager writeBackManager = new WriteBackManager();
        writeBackManager.setManager(manager);
        return writeBackManager;
    }

    private static final String getPackageName() {

        return new Object() {
            public String getClassForStatic() {
                return this.getClass().getPackage().getName();
            }
        }.getClassForStatic();
    }

}
